package com.yiji.fintech.musfinance.common.enginerules.rules;

import com.acooly.core.utils.Collections3;
import com.yiji.fintech.musfinance.common.annotation.RuleNameAnnotation;
import com.yiji.fintech.musfinance.common.exception.AbortBizException;
import com.yiji.fintech.musfinance.common.enginerules.base.RulesFilter;
import com.yiji.fintech.musfinance.common.domain.channel.ChannelDomain;
import com.yiji.fintech.musfinance.common.domain.channel.InstChannelApiDomain;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * 权重规则
 * Created by ouwen@yiji.com} on 2017/3/30.
 */
@Service
@RuleNameAnnotation("权重规则服务")
public class WeightRulesService extends RulesFilter {
    @Override
    protected void filter(ChannelDomain domain){
        // 优先级相同为基础
        Iterator<InstChannelApiDomain> iterator = channelApiList.iterator();
        int topPrior = -1;
        while (iterator.hasNext()) {
            InstChannelApiDomain rule = iterator.next();
            if (topPrior == -1) {
                topPrior = rule.getPriority();
                continue;
            }
            int curPrior = rule.getPriority();
            if (curPrior != topPrior) {
                iterator.remove();
            }
        }
        if (channelApiList.size() == 1) {
            return;
        }else if(channelApiList.size() ==0){
            throw new AbortBizException("权重后无可用渠道");
        }
        List<ChannelWeightArea> areas = new ArrayList<>(channelApiList.size());
        int floor = 0;
        for (InstChannelApiDomain rule : channelApiList) {
            int ceiling = floor + rule.getWeight();
            ChannelWeightArea area = new ChannelWeightArea(rule.getGatewayChannelApi(), floor, ceiling);
            floor = ceiling;
            areas.add(area);
        }
        // 生成随机数找对应域,floor是最后一个域的最大值,因为有出现0的可能,所以随机数要*(floor-1)
        int random = (int) Math.round(Math.random() * (floor - 1));
        random = random < 0 ? 0 : random;
        ChannelWeightArea selectedArea = searchWeightAreaIndex(areas, random);
        // 如果未命中，则直接返回，筛选第一条即可
        if (selectedArea == null) {
            return;
        }
        iterator = channelApiList.iterator();
        while (iterator.hasNext()) {
            InstChannelApiDomain rule = iterator.next();
            if (!StringUtils.equals(selectedArea.getKey(), rule.getGatewayChannelApi())) {
                iterator.remove();
            }
        }
    }
    // 权重域
    private ChannelWeightArea searchWeightAreaIndex(List<ChannelWeightArea> areas, int random) {
        for (int i = 0; i < areas.size(); i++) {
            ChannelWeightArea area = areas.get(i);
            if (random >= area.getFloor() && random < area.getCeiling()) {
                return area;
            }
        }
        if(Collections3.isNotEmpty(areas)) {
            return areas.get(0);
        }
        return null;
    }
    /**
     * 渠道权重类
     *
     * @author zeyong
     */
    @Data
    public static class ChannelWeightArea {
        private String key;
        private int floor;
        private int ceiling;
        public ChannelWeightArea(String instChannelApi, int floor, int ceiling) {
            this.floor = floor;
            this.ceiling = ceiling;
            this.key = instChannelApi;
        }
        /**
         * @return
         * @see Object#toString()
         */
        @Override
        public String toString() {
            return "[key=" + key + ", floor=" + floor + ", ceiling=" + ceiling + "]";
        }
    }
}
